package com.axzh.multithread.download;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

/**
 * 命令行shell
 * @author wml
 *
 */
public class DLCmd extends DLMain {

	private Scanner scanner = new Scanner(System.in);
	private boolean isQuit;
	private Thread showInfoThread;
	
	public DLCmd() throws IOException {
		super();
	}

	public static void main(String[] args) throws IOException {
		DLCmd cmd = new DLCmd();
		cmd.run(args);
	}

	public void run(String[] args) {
		showHelp();
		
		while(!isQuit) {
			System.err.flush();
			System.out.print(">>> ");
			System.out.flush();
			
			String input = scanner.nextLine().trim();
			
			if(input.isEmpty())
				continue;

			Cmds cmd = getCmd(input);
			if(cmd == null) {
				System.out.println("未知命令: " + input);
				continue;
			}
			
			String options = getOptions(input);
			
			switch (cmd) {
			case help: 		showHelp(); break;
			case info: 		execInfo(options); break;
			case show:      execShow(options); break;
			case hide:      execHide(); break;
			case add: 		execAdd(options); break;
			case set:		execSet(options); break;
			case list: 		execList(options); break;
			case run: 		execRun(options); break;
			case pause: 	execPause(options); break;
			case remove: 	execRemove(options); break;
			case config: 	execConfig(options); break;
			case task:		execTask(options); break;
			case quit: 		execQuit(); break;
			default: 		break;
			}
		}
		
	}

	private void showHelp() {
		System.out.println(
				"**************************************************\n"+
				"******** DLMain java 多线程断点续传下载工具 ********\n"+
				"**************************************************\n"+
				"  help   \t\t显示帮助\n" + 
				"  info [taskid]   \t显示任务进度(有taskid则显示该任务的详情,taskid通过list命令获得)\n" + 
				"  show   \t\t持续显示任务进度(有taskid则显示该任务的详情)\n" + 
				"  hide  \t\t关闭任务进度显示\n" + 
				"  add [url] \t\t添加任务\n" + 
				"  set [prop value] \t设置(prop: threadCount, taskCount, saveDir)\n" + 
				"  list [status]   \t列出任务(status: pause, done, waiting, running), 第一列为taskid, 无status则显示所有\n" + 
				"  run [taskid]    \t开始任务(taskid通过list命令获得), 无taskid则开始所有任务\n" + 
				"  pause [taskid]  \t暂停任务, 无taskid则暂停所有任务\n" + 
				"  remove [taskid] [d]  \t删除任务(d: 删除任务并删除文件)\n" +
				"  config [cfgdir] \t加载配置并设置配置目录\n" +
				"  task [taskid] \t显示任务详细信息\n" +
				"  quit \t\t\t退出\n" +
				"--------------------------------------------------------"
				);
	}

	private void execTask(String options) {
		DLTask task = getTaskByOption(options, true);
		if(task == null) {
			return;
		}
		
		System.out.println("******************** 任务属性 ********************");
		System.out.println("** 文件地址：" + task.getUri());
		System.out.println("** 文件名：" + task.getName());
		System.out.println("** 文件大小：" + DLUtils.getLengthStr(task.getLength()));
		System.out.println("** 断点续传：" + (task.isSupportedContentRange()?"支持":"不支持"));
		System.out.println("** 临时文件：" + task.getTmpfile());
		System.out.println("** 保存位置：" + task.getFile());
		System.out.println("**************************************************");
	}

	private DLTask getTaskByOption(String options, boolean needTaskid) {
		Integer taskid = parseInt(options);
		if(taskid == null) {
			if(needTaskid)
				System.out.println("需要taskid!");
			return null;
		}
			
		DLTask task = findTaskById(taskid);
		if(task == null) {
			System.out.println("没有此任务: " + options);
			return null;
		}
		return task;
	}

	@SuppressWarnings("deprecation")
	private void execShow(final String options) {
		
		if(options != null) {
			DLTask task = getTaskByOption(options, false);
			if(task == null) {
				return;
			}
		}
		
		if(showInfoThread != null) {
			showInfoThread.stop();
		}
		
		showInfoThread = new Thread("show-info-thread") {
			@Override
			public void run() {
				while(showInfoThread != null) {
					execInfo(options);
					try {
						sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		showInfoThread.setDaemon(true);
		showInfoThread.start();
	}

	private void execHide() {
		showInfoThread = null;
	}

	private void execInfo(String options) {
		if(options!=null) {
			
			DLTask task = getTaskByOption(options, false);
			if(task == null) {
				return;
			}

			System.out.println(task);
			if(task.getBlocks()!=null) {
				for (DLBlock block : task.getBlocks()) {
					System.out.println(block);
				}
			}
			
		} else {
			synchronized (getRunningTasks()) {
				for (DLTask task : getRunningTasks()) {
					System.out.println(task);
				}
			}
		}
	}

	private void execAdd(String options) {
		if(options == null) {
			System.out.println("需要url!");
			return;
		}
		
		if(!options.toLowerCase().startsWith("http")) {
			options = "http://" + options;
		}
		
		if(hasTask(options)) {
			System.out.println("任务`"+options+"`已存在！");
			return;
		}
		
		DLTask task = null;
		try {
			task = getTaskUriInfo(options);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		if(task == null) {
			System.out.println("获取文件信息失败，请稍后再试");
			return;
		}
		
		boolean ok = confirm("下载确认",
				"** 文件地址: " + task.getUri() + "\n" +
				"** 保存位置: " + task.getFile() + "\n" +
				"** 却定要下载吗？");
		
		if(ok) {
			try {
				addTask(task);
			} catch (IOException e) {
				e.printStackTrace();
				System.out.println("文件创建失败！" + task.getFile());
				return;
			}
			startTask(task);
			
			System.out.println("添加并开始任务：" + task.getName());
		}
	}

	private void execSet(String options) {
		if(options == null)
			return;
		
		String prop;
		String value;

		int pos = options.indexOf(' ');
		if(pos != -1) {
			prop = options.substring(0, pos).trim();
			value = options.substring(pos+1).trim();
			
			Integer ival = parseInt(value);
			if(prop.equals("threadCount")) {
				if(ival == null || ival < 1) {
					System.out.println("值无效！");
					return;
				}
				
				setThreadCount(ival);
			} else if(prop.equals("taskCount")) {
				if(ival == null || ival < 1) {
					System.out.println("值无效！");
					return;
				}

				setTaskCount(ival);
			}  else if(prop.equals("saveDir")) {
				setSaveDir(value);
			} else {
				System.out.println("未知配置项！");
				return;
			}
			
			System.out.println("`"+prop+"`已更为" + value + "!");
			
		} else {
			System.out.println("请填写`"+options+"`的值！");
		}
	}

	private void execConfig(String options) {
		if(options == null) {
			System.out.println("需要cfgdir!");
			return;
		}
		try {
			loadConfigs(options);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void execList(String options) {
		for (DLTask task : getTasks()) {
			if(options == null || task.isRunning() && options.equalsIgnoreCase("running")) {
				System.out.println(task);
			} else if(task.isDone() && options.equalsIgnoreCase("done")) {
				System.out.println(task);
			} else if(task.isPause() && options.equalsIgnoreCase("pause")) {
				System.out.println(task);
			} else if(task.isWaiting() && options.equalsIgnoreCase("waiting")) {
				System.out.println(task);
			}
		}
	}

	private void execRun(String options) {
		if(options!=null) {
			DLTask task = getTaskByOption(options, false);
			if(task == null) {
				return;
			}

			startTask(task);
			System.out.println("开始任务：" + task.getName());
		} else {
			startAll();
			System.out.println("开始所有任务！");
		}
	}

	private void execRemove(String options) {
		if(options == null) {
			System.out.println("需要taskid!");
			return;
		}
		
		boolean delete = false;
		DLTask task = null;

		int pos = options.indexOf(' ');
		if(pos != -1) {
			task = getTaskByOption(options.substring(0, pos).trim(), true);
			delete = options.substring(pos+1).trim().equalsIgnoreCase("d");
		} else {
			task = getTaskByOption(options, true);
		}
		
		if(task == null) {
			return;
		}
		
		if(delete) {
			System.out.println("删除任务和文件：" + task.getName());
		} else {
			System.out.println("删除任务：" + task.getName());
		}
		
		removeTask(task, delete);
	}

	private void execPause(String options) {
		if(options!=null) {
			DLTask task = getTaskByOption(options, false);
			if(task == null) {
				return;
			}
		
			task.setStatus(DLTask.STATUS_PAUSE);
			System.out.println("暂停任务：" + task.getName());
			System.out.println(task);
		} else {
			for (DLTask task : getTasks()) {
				if(task.isRunning()||task.isWaiting())
					task.setStatus(DLTask.STATUS_PAUSE);
			}
			System.out.println("暂停所有任务！");
		}
	}

	private void execQuit() {
		for (DLTask task : new ArrayList<DLTask>(getRunningTasks())) {
			if(task.isRunning())
				task.setStatus(DLTask.STATUS_PAUSE);
		}
		isQuit = true; 
		System.out.println("欢迎使用！");
	}

	private Integer parseInt(String value) {
		if(value == null)
			return null;
		try {
			return Integer.valueOf(value);
		} catch (NumberFormatException e) {
			return null;
		}
	}

	@Override
	protected void onTaskStatusChange(DLTask task) {
		super.onTaskStatusChange(task);
		
		if(task.isDone())
			System.out.println("`" + task.getName() + "`下载完成！");
	}

	private boolean confirm(String title, String message) {
		System.out.print("**************** " + title + " ****************\n" + message +
				"\n>>> yes/no? (Y/N): ");
		return scanner.nextLine().equalsIgnoreCase("y");
	}

	private String getOptions(String input) {
		int pos = input.indexOf(' ');
		if(pos != -1) 
			return input.substring(pos + 1).trim();
		return null;
	}

	private Cmds getCmd(String input) {
		String cmd;
		int pos = input.indexOf(' ');
		if(pos != -1) 
			cmd = input.substring(0, pos);
		else
			cmd = input;
		
		try {
			return Cmds.valueOf(cmd);
		} catch (IllegalArgumentException e) {
			return null;
		}
	}
	
	public enum Cmds {
		help, info, show, hide, add, set, list, run, pause, config, quit, remove, task
	}
}
